<template>
    <div class="streaming-message">
      <div class="message-content" ref="contentElement">
        {{ displayedContent }}
        <span v-if="isStreaming" class="cursor"></span>
      </div>
    </div>
  </template>
  
  <script lang="ts">
  import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
  
  @Component
  export default class StreamingMessage extends Vue {
    @Prop({ required: true }) content!: string;
    @Prop({ default: false }) isStreaming!: boolean;
  
    displayedContent = '';
    private animationFrameId?: number;
  
    mounted() {
      this.animateText();
    }
  
    beforeDestroy() {
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId);
      }
    }
  
    @Watch('content')
    onContentChange(newVal: string, oldVal: string) {
      if (newVal.length > oldVal.length) {
        this.animateText();
      } else {
        this.displayedContent = newVal;
      }
    }
  
    private animateText() {
      const targetLength = this.content.length;
      let currentLength = this.displayedContent.length;
  
      const animate = () => {
        if (currentLength < targetLength) {
          this.displayedContent = this.content.slice(0, ++currentLength);
          this.animationFrameId = requestAnimationFrame(animate);
          this.scrollToVisible();
        }
      };
  
      this.animationFrameId = requestAnimationFrame(animate);
    }
  
    private scrollToVisible() {
      const element = this.$refs.contentElement as HTMLElement;
      if (element) {
        element.scrollIntoView({ 
          behavior: 'smooth', 
          block: 'nearest' 
        });
      }
    }
  }
  </script>
  
  <style scoped>
  .streaming-message {
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-word;
  }
  
  .message-content {
    position: relative;
    padding-right: 8px;
  }
  
  .cursor {
    position: relative;
    display: inline-block;
    width: 2px;
    margin-left: 2px;
    background-color: currentColor;
    animation: blink 1s step-end infinite;
  }
  
  @keyframes blink {
    0%, 100% { opacity: 1; }
    50% { opacity: 0; }
  }
  </style>